﻿///******************** NG.Respate(C)  **********************************
//* 产品名称: SD卡烧录工具
//* 程序作者: Respate(@ 南宫子萍)
//* 程序版本: V1.1														   
//* 编制日期: 2020/7/18
//* 功能描述: windows下简易dd命令
//* SPDX-License-Identifier:	GPL-2.0+DEBUG_ADD
//* QQ:	2085827949
//**********************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


//一、dd命令的解释
//dd：用指定大小的块拷贝一个文件，并在拷贝的同时进行指定的转换。
//注意：指定数字的地方若以下列字符结尾，则乘以相应的数字：b=512；c=1；k=1024；w=2
//参数注释：
//1. if=文件名：输入文件名，缺省为标准输入。即指定源文件。< if=input file >
//2. of=文件名：输出文件名，缺省为标准输出。即指定目的文件。< of=output file >
//3. ibs=bytes：一次读入bytes个字节，即指定一个块大小为bytes个字节。
//    obs=bytes：一次输出bytes个字节，即指定一个块大小为bytes个字节。
//    bs=bytes：同时设置读入/输出的块大小为bytes个字节。
//4. cbs=bytes：一次转换bytes个字节，即指定转换缓冲区大小。
//5. skip=blocks：从输入文件开头跳过blocks个块后再开始复制。
//6. seek=blocks：从输出文件开头跳过blocks个块后再开始复制。
//注意：通常只用当输出文件是磁盘或磁带时才有效，即备份到磁盘或磁带时才有效。
//7. count=blocks：仅拷贝blocks个块，块大小等于ibs指定的字节数。
//8. conv=conversion：用指定的参数转换文件。
//    ascii：转换ebcdic为ascii
//     ebcdic：转换ascii为ebcdic
//    ibm：转换ascii为alternate ebcdic
//    block：把每一行转换为长度为cbs，不足部分用空格填充
//    unblock：使每一行的长度都为cbs，不足部分用空格填充
//    lcase：把大写字符转换为小写字符
//    ucase：把小写字符转换为大写字符
//    swab：交换输入的每对字节
//     noerror：出错时不停止
//     notrunc：不截短输出文件
//    sync：将每个输入块填充到ibs个字节，不足部分用空（NUL）字符补齐

namespace WSLDD
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            string inFile = ""; // 输入文件名称
            string outFile= ""; // 输出文件名称
            string SEEK = "";   // 输出偏移量
            string BS = "";     // 扇区单位

            // use 控制台
            if (args.Length > 0)
            {
                // 解析控制台传入参数
                foreach (string arg in args)
                {
                    if (arg.Contains("if="))
                        inFile = arg.Substring(arg.IndexOf("=") + 1);

                    else if (arg.Contains("of="))
                        outFile = arg.Substring(arg.IndexOf("=") + 1);

                    else if (arg.Contains("seek="))
                    {
                         SEEK = arg.Substring(arg.IndexOf("=") + 1);
                    }
                    else if (arg.Contains("bs="))
                    {
                        BS = arg.Substring(arg.IndexOf("=") + 1);
                    }
                }

                // fusing image
                Console.WriteLine( Program.fusing(inFile, outFile, SEEK, BS) );
            }
            else // 使用窗口
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }



        //string inFile = ""; // 输入文件名称
        //string outFile = ""; // 输出文件名称
        //int SEEK = 0;       // 输出偏移量
        //int BS = 512;       // 扇区单位
        //
        public static string fusing(string inFile, string outFile, string _seek, string _bs = "512")
        {
            int i = 0;
            int rseek = 0;
            string msg = "";

            // 容错判断
            if (inFile == "" || outFile == "" || _seek == "")
            {
                msg += "\nfusing args Err!\r\n";
                msg += "in:" + inFile + "\r\n";
                msg += "0f:" + outFile + "\r\n";
                msg += "seek:" + _seek + "\r\n";
                msg += "bs:" + _bs + "\r\n";
                goto err;
            }

            // 解析数据
            int  seek = Int16.Parse(_seek);
            int bs = 512;
            int isk = 1;
            if (_bs.Contains("k") || _bs.Contains("K"))
            {
                isk = 2;
                string temp = _bs;
                _bs = temp.Substring(0, temp.Length - 1);
            }
            bs = Int16.Parse(_bs);
            bs *= 512 * isk;
            if (bs < 0 || (bs % 512) != 0) bs = 512;


            msg += "in:" + inFile + "\r\n";
            msg += "0f:" + outFile + "\r\n";

            // 计算扇区偏移量
            rseek = seek*(bs / 512);
            msg += "seek:" + rseek + "  bs:" + bs + "\r\n";

            LAP.Disk disk = new LAP.Disk(outFile);      // 打开盘符
            disk.setDiskMode(LAP.Disk.DISKMODE.PHYSIC); // 设置访问模式
            LAP.File uboot = new LAP.File(inFile);      // 打开文件

            // 检查磁盘与文件状态
            if (uboot.GetFileSize() <= 0 || !disk.isAvailable())
                goto err;

            int toall = 0; // 统计烧录字节数
            byte[] buff = new byte[512];    // 数据缓冲区
            for (i = 0; i < uboot.GetFileSize(); i += 512)
            {
                int len = uboot.Read(buff, i, 512);     // 读取文件
                disk.WritSector(buff, rseek + (i / 512), len);   // 写入文件(扇区)
                toall += len;
                if (len < 512) break;   // 容错判断
            }

            // 将烧录字节数转为合适单位，并输出到控制台
            string info = "";
            if ((toall / (1024 * 1024)) > 0) info = (toall / (1024.0 * 1024)) + " Mb";
            else if ((toall / (1024)) > 0) info = (toall / (1024.0)) + " Kb";
            msg += "fusing " + info + "  [" + toall + " Bytes]\r\n";

            msg += disk.logText;
            disk.logText = "";

        err:
            return msg;
        }
    }

}




